/**
 * ____________________ *
 *  ____ ____ ____ _  _ *
 *  |___ [__] |--< |\/| *
 * ____________________ *
 *
 * THE CORM PROJECT
 *
 * This file may only be used in accordance with the
 * terms of the Academic Free License ("AFL") v. 3.0,
 * as published by the Open Software Initiative.  A
 * copy of this license is provided in this source
 * release, and may be viewed online at:
 *
 * (http://www.opensource.org/licenses/afl-3.0.php)
 */
package org.eremite.corm.party.relationship;

import org.apache.openjpa.persistence.*;
import org.eremite.corm.BaseArchetype;
import org.eremite.corm.party.Party;

import javax.persistence.*;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

@Entity
@FetchGroups(
        @FetchGroup(name="withRelationships", attributes={
        @FetchAttribute(name="assignedResponsibilities"),
        @FetchAttribute(name="relationships")}))
public class PartyRole<P extends Party>
        extends BaseArchetype {

    @ManyToOne(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE})
    @Column(nullable=false)
    @Type(Party.class)
    private P party;

    @ManyToOne(cascade = {
            CascadeType.PERSIST,
            CascadeType.MERGE})
    @Column(nullable=false)
    private PartyRoleType type;

    @OneToMany(cascade=CascadeType.ALL)
    private Set<AssignedResponsibility> assignedResponsibilities =
            new HashSet<AssignedResponsibility>();

    @ManyToMany(cascade={
            CascadeType.PERSIST,
            CascadeType.MERGE},
            mappedBy="participants")
    @ElementType(PartyRelationship.class)
    Set<PartyRelationship<P>> relationships = new HashSet<PartyRelationship<P>>();

    /* Default Constructor */
    public PartyRole(){}

    /* Convenience Constructor */
    public PartyRole(PartyRoleType type, P party) {
        setPartyRoleType(type);
        setParty(party);
        party.addPartyRole(this);
    }

    /* PartyRole can be associated with exactly 1 Party */
    public P getParty() {
        return this.party;
    }
    
    public void setParty(P party) {
        this.party = party;
    }

    /* PartyRole has exactly one PartyRoleType */
    public PartyRoleType getPartyRoleType() {
        return this.type;
    }
    public void setPartyRoleType(PartyRoleType type) {
        this.type = type;
    }

    /* PartyRole has 0 or more AssignedResponsibilities */
    public Set<AssignedResponsibility> getAssignedResponsibilities() {
        return this.assignedResponsibilities;
    }

    public void setAssignedResponsibilities(Set<AssignedResponsibility> assignedResponsibilities) {
        this.assignedResponsibilities = assignedResponsibilities;
    }

    public Set<PartyRelationship<P>> getRelationships() {
        return relationships;
    }

    public void setRelationships(Set<PartyRelationship<P>> relationships) {
        this.relationships = relationships;
    }

    public void addPartyRelationship(PartyRelationship<P> rel) {
        getRelationships().add(rel);
    }

    public void addPartyRelationship(PartyRelationship<P> ... rels) {
        for(PartyRelationship<P> rel : rels) {
            addPartyRelationship(rel);
        }
    }

    public void addAssignedResponsibility (AssignedResponsibility ... assignedResponsibilities ) {
        getAssignedResponsibilities().addAll(Arrays.asList(assignedResponsibilities));
    }

    public void addAssignedResponsibility (AssignedResponsibility assignedResponsibility) {
        getAssignedResponsibilities().add(assignedResponsibility);
    }
}
